package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.common.utils.uuid.UUID;
import com.zzyl.nursing.dto.DeviceDetailVo;
import com.zzyl.nursing.dto.DeviceDto;
import com.zzyl.nursing.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 设备表Service业务层处理
 *
 * @author alexis
 * @date 2025-06-05
 */
@Slf4j
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private IoTDAClient iotdaClient;
    @Autowired
    private DeviceMapper deviceMapper;



    /**
     * 查询设备表
     *
     * @param id 设备表主键
     * @return 设备表
     */
    @Override
    public Device selectDeviceById(Long id) {
        return deviceMapper.selectById(id);
    }

    /**
     * 查询设备表列表
     *
     * @param device 设备表
     * @return 设备表
     */
    @Override
    public List<Device> selectDeviceList(Device device) {
        return deviceMapper.selectDeviceList(device);
    }

    /**
     * 新增设备表
     *
     * @param device 设备表
     * @return 结果
     */
    @Override
    public int insertDevice(Device device) {
        return deviceMapper.insert(device);
    }

    /**
     * 修改设备表
     *
     * @param device 设备表
     * @return 结果
     */
    @Override
    public int updateDevice(Device device) {
        return deviceMapper.updateById(device);
    }

    /**
     * 批量删除设备表
     *
     * @param ids 需要删除的设备表主键
     * @return 结果
     */
    @Override
    public int deleteDeviceByIds(Long[] ids) {
        return deviceMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除设备表信息
     *
     * @param id 设备表主键
     * @return 结果
     */
    @Override
    public int deleteDeviceById(Long id) {
        return deviceMapper.deleteById(id);
    }

    @Override
    public void syneProductList() {
        // 1. 查询 iot 平台产品列表
        ListProductsRequest request = new ListProductsRequest();
        request.setLimit(50);
        ListProductsResponse response = iotdaClient.listProducts(request);

        if (response.getHttpStatusCode() != 200) {
            throw new IllegalStateException("查询产品列表失败！");
        }

        List<ProductSummary> products = response.getProducts();
        if (CollectionUtil.isEmpty(products)) {
            log.warn("iot平台没有产品");
        }

        // 2. 转为 JSON 字符串再存入 Redis
        String json = JSONUtil.toJsonStr(products);
        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, json);
    }


    @Override
    public List<ProductVo> allProduct() {
        String value = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);
        if (StringUtils.isEmpty(value)) {
            return Collections.emptyList();
        }
        return JSONUtil.toList(value, ProductVo.class);
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //1 判断设备名称是否重复
        Long count = lambdaQuery()
                .eq(Device::getDeviceName, deviceDto.getDeviceName())
                .count();
        if (count > 0) {
            throw new BaseException("设备名称重复！");
        }
        //2.  判断设备标识码是否重复
        count = lambdaQuery()
                .eq(Device::getNodeId, deviceDto.getNodeId())
                .count();
        if (count > 0) {
            throw new BaseException("设备标识码重复！");
        }
        //3.判断同一位置是否绑定了相同的产品
        count = lambdaQuery()
                .eq(Device::getBindingLocation, deviceDto.getBindingLocation())
                .eq(Device::getProductKey, deviceDto.getProductKey())
                .eq(Device::getLocationType, deviceDto.getLocationType())
                .eq(Device::getPhysicalLocationType, deviceDto.getPhysicalLocationType())
                .count();
        if (count > 0) {
            throw new BaseException("同一位置已绑定相同产品！");

        }
//4.注册设备到华为iot平台
        //随机生成一个密钥
        String secret = UUID.randomUUID().toString().replaceAll("-", "");

        AddDeviceRequest addDeviceRequest = new AddDeviceRequest();
        AddDevice addDevice = new AddDevice();
        addDevice
                .withDeviceName(deviceDto.getDeviceName())
                .withNodeId(deviceDto.getNodeId())
                .withProductId(deviceDto.getProductKey())
                .withAuthInfo(new AuthInfo()
                        .withSecret(secret));

        addDeviceRequest.withBody(addDevice);
        AddDeviceResponse response = null;
        try {
            response = iotdaClient.addDevice(addDeviceRequest);
        } catch (Exception e) {
           log.error("注册设备到华为iot平台失败！", e);
        throw new BaseException("注册设备到华为iot平台失败！");
        }

        /*保存设备数据到数据库*/
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setSecret(secret);
        device.setIotId(response.getDeviceId());
        save(device);
    }

    @Override
    public DeviceDetailVo queryDeviceDetail(String iotId) {
    //1 查询数据库
Device device = getOne(Wrappers.<Device>lambdaQuery().eq(Device::getIotId, iotId));
if(ObjectUtil.isEmpty(device)){
    return null;
}

        //2调用华为云物联网接口
        ShowDeviceRequest request = new ShowDeviceRequest();
       request.setDeviceId(iotId);
        ShowDeviceResponse response;
        try {
            response =iotdaClient.showDevice(request);
        } catch (Exception e) {
            log.info("查询设备详情失败！:{}", e.getMessage());
            throw new BaseException("查询设备详情失败！");
        }
        //属性拷贝
        DeviceDetailVo deviceDetailVo = BeanUtil.toBean(device, DeviceDetailVo.class);
        deviceDetailVo.setDeviceStatus(response.getStatus());

        //3合并数据返回结果

        deviceDetailVo.setDeviceStatus(response.getStatus());
        String activeTimeStr = response.getActiveTime();
        if(StringUtils.isNotEmpty(activeTimeStr)){
            LocalDateTime activeTime = LocalDateTimeUtil.parse(activeTimeStr, DatePattern.UTC_MS_PATTERN);
            //日期时区转换
            activeTime = activeTime.atZone(ZoneId.from(ZoneOffset.UTC))
                    .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                    .toLocalDateTime();
            deviceDetailVo.setActiveTime(activeTime);
        }
        return deviceDetailVo;

    }

    @Override
    public int updateDateById(DeviceDto deviceDto) {
        // 1. 验证设备是否存在
        Device existingDevice = getOne(Wrappers.<Device>lambdaQuery()
                .eq(Device::getId, deviceDto.getId()));
        if (ObjectUtil.isEmpty(existingDevice)) {
            throw new BaseException("设备不存在");
        }

        // 2. 更新华为云IoT平台设备信息
        UpdateDeviceRequest updateRequest = new UpdateDeviceRequest();
        UpdateDevice updateDevice = new UpdateDevice()
                .withDeviceName(deviceDto.getDeviceName());


        updateRequest.withDeviceId(existingDevice.getIotId())
                .withBody(updateDevice);

        try {
            UpdateDeviceResponse response = iotdaClient.updateDevice(updateRequest);
            if (response.getHttpStatusCode() != 200) {
                throw new BaseException("华为云IoT平台更新失败");
            }
        } catch (Exception e) {
            log.error("华为云设备更新失败", e);
            throw new BaseException("华为云设备更新失败: " + e.getMessage());
        }

        // 3. 更新本地数据库
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setId(existingDevice.getId());
        device.setIotId(existingDevice.getIotId());
        device.setProductKey(deviceDto.getProductKey());
        device.setLocationType(deviceDto.getLocationType());
        device.setPhysicalLocationType(deviceDto.getPhysicalLocationType());
        // 方案1：如果业务上bindingLocation应该是String类型
        device.setBindingLocation(String.valueOf(deviceDto.getBindingLocation()));

// 方案2：如果业务上bindingLocation应该是Long类型，则需要修改Device类字段类型
// 需要同时修改Device类中的bindingLocation字段类型为Long
// device.setBindingLocation(deviceDto.getBindingLocation());

        return deviceMapper.updateById(device);

    }

    @Override
    public int delet(String iotId) {
        log.info("开始删除设备：{}", iotId);

        // 1. 先检查本地数据库是否存在该设备
        Device device = getOne(Wrappers.<Device>lambdaQuery()
                .eq(Device::getIotId, iotId));
        if (ObjectUtil.isEmpty(device)) {
            throw new BaseException("本地设备不存在");
        }

        // 2. 尝试删除华为云IoT平台设备
        try {
            DeleteDeviceRequest deleteRequest = new DeleteDeviceRequest();
            deleteRequest.setDeviceId(iotId);
            DeleteDeviceResponse response = iotdaClient.deleteDevice(deleteRequest);

            if (response.getHttpStatusCode() != 200 && response.getHttpStatusCode() != 204) {
                throw new BaseException("华为云IoT平台删除失败，状态码: " + response.getHttpStatusCode());
            }

            // 记录删除结果日志
            if (response.getHttpStatusCode() == 404) {
                log.warn("华为云设备不存在，继续删除本地记录: {}", iotId);
            } else {
                log.info("华为云设备删除成功: {}", iotId);
            }
        } catch (ServiceResponseException e) {
            if (e.getHttpStatusCode() == 404) {
                log.warn("华为云设备不存在(异常捕获)，继续删除本地记录: {}", iotId);
            } else {
                log.error("华为云服务异常", e);
                throw new BaseException("华为云服务异常: " + e.getMessage());
            }
        } catch (Exception e) {
            log.error("华为云设备删除异常", e);
            throw new BaseException("华为云设备删除异常: " + e.getMessage());
        }

        // 3. 删除本地数据库记录
        int deletedCount = deviceMapper.delete(Wrappers.<Device>lambdaQuery()
                .eq(Device::getIotId, iotId));

        if (deletedCount == 0) {
            log.error("本地设备删除失败: {}", iotId);
            throw new BaseException("本地设备删除失败");
        }

        log.info("本地设备删除成功: {}", iotId);
        return deletedCount;
    }



}
